import React, { useEffect, useRef, useState } from 'react';

import { ReactComponent as CheckMarkBig } from '@/assets/images/auth/ChevronDownBig.svg';
import { ReactComponent as CheckMark } from '@/assets/images/shared/icon-check2.svg';
import { ReactComponent as Chevron } from '@/assets/images/shared/icon-chevron.svg';
import { SelectProps } from '@/shared/interfaces';
import { transformArrayIntoObject } from '@/shared/lib/transformArrayIntoObject';
import { Loader } from '@/shared/ui/Loader';
import cn from 'classnames';
import { useOnClickOutside } from 'usehooks-ts';

import cs from './Select.module.scss';

export const Select = ({
  config,
  disabled,
  onSelect,
  selected,
  withSmallFont,
  className,
  width,
  isBig,
  isHover = true,
  withCheckmark,
  isSingle,
  withPlaceholder,
  placeholderClassName,
  containerClassName,
  isRight,
  isFullWidth,
}: {
  config: { title: string; values: SelectProps[] | undefined };
  disabled?: boolean;
  onSelect: (args: unknown & SelectProps) => void;
  selected: (unknown & SelectProps)[];
  className?: string;
  withSmallFont?: boolean;
  width?: number | string;
  isBig?: boolean;
  placeholderClassName?: string | null;
  containerClassName?: string;
  withPlaceholder?: string;
  withCheckmark?: boolean;
  isSingle?: boolean;
  isHover?: boolean;
  isRight?: boolean;
  isFullWidth?: boolean;
}) => {
  const [isClosing, setIsClosing] = useState(false);
  const [isPlaceholder, setIsPlaceholder] = useState(true);
  const isSelected = (item: SelectProps): boolean => !!selected.find((i) => i.id.toString() === item.id.toString());
  const [isOpen, setIsOpen] = useState(false);
  const handleClose = () => {
    if (isHover) {
      return;
    }
    setIsOpen(() => false);
  };
  const handleSelect = (item: SelectProps) => {
    setIsPlaceholder(false);
    onSelect(item);
    handleClose();

    if (isSingle) {
      setIsClosing(() => true);
      setTimeout(() => {
        setIsClosing(() => false);
      }, 0);
    }
  };
  const handleToggle = () => {
    setIsOpen((value) => !value);
  };
  const ref = useRef<HTMLDivElement>(null);

  useEffect(
    () => () => {
      setIsPlaceholder(true);
    },
    [],
  );

  useOnClickOutside(ref, handleClose);
  return (
    <div
      className={cn(cs.select, isHover && cs.hover, isOpen && cs.open, disabled && cs.disabled, containerClassName)}
      ref={ref}
    >
      <button
        className={cn(cs.button, className)}
        data-testid="select"
        onClick={() => !isHover && handleToggle()}
        type="button"
      >
        {(isPlaceholder && !config.title && withPlaceholder && (
          <span className={cn(placeholderClassName !== null && cs.placeholder)}>{withPlaceholder}</span>
        )) || <span>{config.title}</span>}
        {isBig ? <CheckMarkBig className={cs.chevron} /> : <Chevron className={cs.chevron} height={16} width={16} />}
      </button>
      <div
        className={cn(
          cs.body,
          isSingle && isClosing && cs.close,
          isRight ? cs.right : cs.left,
          isFullWidth && cs.IsFullWidth,
          isFullWidth && cs.bodyCenter,
        )}
      >
        {config?.values?.map((item, index) => (
          <button
            className={cn(
              isFullWidth ? cs.itemWithFullWidth : cs.item,
              isSelected(item) && cs.active,
              withSmallFont && cs.withSmallFont,
            )}
            data-testid={`option-${index}`}
            key={item?.id}
            onClick={() => handleSelect(item)}
            style={{ width }}
            type="button"
          >
            <span>{item?.title}</span>
            {withCheckmark && (
              <span className={cs.checked}>
                {isSelected(item) && withCheckmark && <CheckMark height={16} width={16} />}
              </span>
            )}
          </button>
        ))}
        {!config?.values &&
          transformArrayIntoObject(Array(4).fill(1)).map(({ id }) => (
            <Loader borderRadius={12} height={46} key={id} width={Number(width) || 100} />
          ))}
      </div>
    </div>
  );
};
